package abel.wlmr.model.unit;

import abel.util.HexString;
import abel.wlmr.model.WlmrBaseUnit;
import abel.wlmr.model.WlmrException;
import io.netty.buffer.ByteBuf;

/**
 * B.5.13.1.3 F1：文件传输方式1
 * 数据体格式见表 B.211。
 * 表B.210 文件传输方式 1 数据单元格式
 * 数据内容 数据格式 字节数
 * 文件标识 BIN 1
 * 文件属性 BIN 1
 * 
 * 文件指令 BIN 1
 * 总段数 n BIN 2
 * 第 i 段标识或偏移（i=0～n-1） BIN 4
 * 第 i 段数据长度 Lf BIN 2
 * 文件数据 BIN Lf
 * 
 * @author Abel
 *
 */
public class Afn0FF1Unit extends WlmrBaseUnit {
    private static final short MIN_LENGTH = 1 + 1 + 1 + 2 + 4 + 2;

    private short fileId;

    private short fileAttr;

    private short fileCmd;

    private int count;

    private long offset;

    private int lf;

    private HexString data;

    public Afn0FF1Unit() {
        super();
    }

    public Afn0FF1Unit(short guessedLen) {
        super(guessedLen);
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        buf.writeByte(fileId);
        buf.writeByte(fileAttr);
        buf.writeByte(fileCmd);
        buf.writeShortLE(count);
        buf.writeIntLE((int) offset);
        buf.writeShortLE(lf);
        buf.writeBytes(data.getBs());

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (checkBuffer(buf) < 0) {
            return -1;
        }

        int len = MIN_LENGTH;
        {
            ByteBuf dup = buf.duplicate();
            dup.skipBytes(1 + 1 + 1 + 2 + 4);
            lf = dup.readUnsignedShortLE();
            len += lf;
            if (getGuessedLength() < len) {
                throw new WlmrException("not enough bytes for 0F.1 body");
            }
        }

        fileId = (short) (buf.readByte() & 0xFF);
        fileAttr = (short) (buf.readByte() & 0xFF);
        fileCmd = (short) (buf.readByte() & 0xFF);
        count = buf.readUnsignedShortLE();
        offset = buf.readLongLE();
        buf.skipBytes(2);
        data = new HexString(buf, lf);

        return len;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.WlmrDataPart#getMinLength()
     */
    @Override
    public int getMinLength() {
        return MIN_LENGTH;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#getFinalLen()
     */
    @Override
    public short getFinalLen() {
        short len = MIN_LENGTH;

        len += lf;

        return len;
    }
}
